﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RapidAddition.FIXEngine;
using RapidAddition.FIXDataDictionary;

namespace LiquidTrading.RapidAdditionHelper.Clients
{
    /// <summary>
    /// Client comms base class
    /// </summary>
    public class FIXClient : IDisposable, RapidAddition.FIXEngine.IFIXSessionCallback
    {
        /// <summary>
        /// Use file based FIX dictionary repository, with a database logger
        /// </summary>
        /// <param name="creds"></param>
        public FIXClient(Credentials.FileRepoDBLog creds)
        {            
            FIXDataDictionary = new CFIXDataDictionary(creds.RepoLocation, creds.FIXVersion);

            Id = creds.Id;

            FIXSender = new CFIXParty(creds.FIXSenderId, creds.FIXSenderId, "", 0);
            FIXCounterparty = new CFIXParty(creds.FIXTargetId, creds.FIXTargetId, creds.FIXHost, creds.FIXPort);

            FIXConversation = new CFIXConversation(FIXSender, FIXCounterparty, creds.FIXVersion, true, 120, false);
            FIXConversation.ConnectRetryInterval = 10;

            System.Data.SqlClient.SqlConnection sql =
                new System.Data.SqlClient.SqlConnection(
                    "Data Source=" + creds.DBHost + "; Initial Catalog=" + creds.DBName + ";Persist Security Info=True; User ID=" + creds.DBUser + "; Password=" + creds.DBPass + ";");

            sql.Open();

            FIXMessageStore = new CFIXMessageStoreSqlServer(sql, FIXConversation);

            FIXSession = new CFIXSession(FIXConversation, FIXDataDictionary, FIXMessageStore, this, null); 
        }

        /// <summary>
        /// Use file based FIX dictionary repository, with a database logger
        /// </summary>
        /// <param name="creds"></param>
        public FIXClient(Credentials.FileRepoFileLog creds)
        {
            FIXDataDictionary = new CFIXDataDictionary(creds.RepoLocation, creds.FIXVersion);

            Id = creds.Id;

            FIXSender = new CFIXParty(creds.FIXSenderId, creds.FIXSenderId, "", 0);

            FIXCounterparty = new CFIXParty(creds.FIXTargetId, creds.FIXTargetId, creds.FIXHost, creds.FIXPort);
            FIXConversation = new CFIXConversation(FIXSender, FIXCounterparty, creds.FIXVersion, true, 120, false);
            FIXConversation.ConnectRetryInterval = 10;
                           
            FIXMessageStore = new CFIXMessageStore(creds.LogLocation, FIXConversation, creds.LogAllMessages);
            FIXMessageStore.Open(false);
            FIXMessageStore.ActivateSession();

            FIXSession = new CFIXSession(FIXConversation, FIXDataDictionary, FIXMessageStore, this, null);            
        }
        
        /// <summary>
        /// Testing client with a file based FIX dictionary repository only
        /// </summary>
        /// <param name="creds"></param>
        public FIXClient(Credentials.TesterFileRepo creds)
        {
            FIXDataDictionary = new CFIXDataDictionary(creds.RepoLocation, creds.FIXVersion);

            Id = creds.Id;
        }

        ~FIXClient()
        {
            if (FIXMessageStore != null)
            {
                FIXMessageStore.DeactivateSession();
                FIXMessageStore.Close();
            }
        }


        public string Id { get; private set; }
        protected CFIXParty FIXSender { get; private set; }
        public CFIXParty FIXCounterparty { get; private set; }
        public CFIXConversation FIXConversation { get; private set; }
        public IFIXMessageStore FIXMessageStore { get; private set; }
        public CFIXDataDictionary FIXDataDictionary { get; private set; }        
        public CFIXSession FIXSession { get; private set; }

        

        public const string FIX42 = "FIX.4.2";
        public bool IsLoggedOut { get { return FIXSession != null ? FIXSession.State == EFIXSessionState.LoggedOut : false; } }


        public virtual void Start()
        {
            if (FIXSession != null)
            {
                FIXSession.LogOn(false);
            }
        }


        #region IFIXSessionCallback Members

        public virtual void NewState(CFIXSession Session, EFIXSessionState State)
        {
            Console.WriteLine("NewState: " + State.ToString());
        }

        public virtual void ReceiveMessage(CFIXSession Session, CFIXMessage Message, int SessionID, int ID, bool DoNotProcess)
        {
            Console.WriteLine("ReceiveMessage: " + SessionID + " " + ID + " " + Message.Message);
        }

        public virtual void SendMessage(CFIXSession Session, CFIXMessage Message)
        {
            Console.WriteLine("SendMessage: " + Message.Message);
        }

        #endregion


        #region IDisposable Members

        public virtual void Dispose()
        {
            if (FIXSession != null && FIXSession.State == EFIXSessionState.LoggedOn)
            {
                FIXSession.LogOff("Disposing FIXClient");
            }
            if (FIXMessageStore != null)
            {
                FIXMessageStore.DeactivateSession();
                FIXMessageStore.Close();                
            }
            FIXSession = null;
            FIXSender = null;
            FIXCounterparty = null;
            FIXConversation = null;
            FIXMessageStore = null;
            FIXDataDictionary = null;
        }

        #endregion
    }
}
